home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / lisp / stk-3.002 / stk-3 / STk-3.1 / Src / signal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-14  |  7.6 KB  |  322 lines

  1. /*
  2.  *
  3.  * s i g n a l . c            -- Signal handling
  4.  *
  5.  * Copyright ⌐ 1993-1996 Erick Gallesio - I3S-CNRS/ESSI <eg@unice.fr>
  6.  * 
  7.  *
  8.  * Permission to use, copy, and/or distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that both the above copyright notice and this permission notice appear in
  11.  * all copies and derived works.  Fees for distribution or use of this
  12.  * software or derived works may only be charged with express written
  13.  * permission of the copyright holder.  
  14.  * This software is provided ``as is'' without express or implied warranty.
  15.  *
  16.  *           Author: Erick Gallesio [eg@unice.fr]
  17.  *    Creation date: 10-Oct-1995 07:55
  18.  * Last file update: 14-Jul-1996 12:34
  19.  *
  20.  */
  21.  
  22. #include "stk.h"
  23. #include <signal.h>
  24.  
  25. #ifdef HAVE_SIGACTION
  26. #  ifdef SA_RESTART
  27. #    define SA_FLAGS SA_RESTART
  28. #  else 
  29. #    define SA_FLAGS 0
  30. #  endif
  31. #endif
  32.  
  33. int STk_sigint_counter = 0;
  34. int STk_control_C      = 0;
  35.  
  36. static SCM signals[MAX_SIGNAL];
  37.  
  38. /* Convention: signals[i] can be 
  39.  *             - #f if signal is ignored
  40.  *            - #t if signal is set to default
  41.  *            - a list of handlers
  42.  */
  43.  
  44.  
  45. static void STk_handle_sigint_signal(void)
  46. {
  47.   SCM l = signals[SIGINT];
  48.   
  49.   STk_control_C = 0;
  50.   if (l == NIL) {
  51.     /* User has not redefined ^C action */
  52. #ifdef HAVE_SIGACTION
  53.     /* Empty the signal mask before calling STk_err, because it will do 
  54.      * a longjmp and don't let the system (at least Linux) a chance to 
  55.      * restore the mask 
  56.      */
  57.     sigset_t set;
  58.     
  59.     sigemptyset(&set);
  60.     sigaddset(&set, SIGINT);
  61.     sigprocmask(SIG_UNBLOCK, &set, NULL);
  62. #endif 
  63.     fprintf(STk_stderr, "*** Interrupt ***\n"); fflush(stderr);
  64.     STk_err("", NIL);
  65.   }
  66.   else {
  67.     SCM arg = LIST1(STk_makeinteger((long) SIGINT));
  68.  
  69.     for ( ; CONSP(l); l = CDR(l)) {
  70.       if (STk_apply(CAR(l), arg) == Sym_break) break;
  71.     }
  72.   }
  73. }
  74.  
  75.  
  76. void STk_handle_signal(int sig)
  77. {
  78.   SCM l, arg;
  79.  
  80. #ifndef  HAVE_SIGACTION
  81.   if (sig < MAX_SYSTEM_SIG)
  82.     signal(sig, STk_handle_signal);
  83. #endif
  84.   if (sig == SIGINT) {
  85.     if (STk_sigint_counter > 0) {
  86.       /* ^C is disallowed for now. (We are probably in sequence which
  87.        * uses malloc). Retain that a Control-C was issued and return
  88.        */
  89.       STk_control_C = 1;
  90.       SET_EVAL_FLAG(1);
  91.       return;
  92.     }
  93.     else STk_handle_sigint_signal();
  94.   }
  95.   
  96.   arg = LIST1(STk_makeinteger((long) sig));
  97.   for (l = signals[sig]; CONSP(l); l = CDR(l)) {
  98.     if (STk_apply(CAR(l), arg) == Sym_break) break;
  99.   }
  100. }
  101.  
  102. PRIMITIVE STk_set_signal_handler(SCM sig, SCM proc)
  103. {
  104.   long s = STk_integer_value(sig);
  105.  
  106.   if (s == LONG_MIN || s < 0 || s >= MAX_SIGNAL)
  107.     STk_err("set-signal-handler!: bad signal number", sig);
  108.  
  109.   if (BOOLEANP(proc)) {
  110.     /* Special case #f means ignore and #t means default */
  111.     void (*handler)() = (proc == Truth) ? SIG_DFL: SIG_IGN;
  112.  
  113. #ifdef HAVE_SIGACTION
  114.     struct sigaction sigact;
  115.     
  116.     sigemptyset(&(sigact.sa_mask));
  117.     sigact.sa_handler = handler;
  118.     sigact.sa_flags   = SA_FLAGS;
  119.     sigaction(s, &sigact, NULL);
  120. #else
  121.     signal(s, handler);
  122. #endif
  123.   }
  124.   else 
  125.     if (STk_procedurep(proc) == Ntruth) 
  126.       STk_err("set-signal-handler!: bad procedure", proc);
  127.  
  128.   return (signals[s] = LIST1(proc));
  129. }
  130.   
  131. PRIMITIVE STk_add_signal_handler(SCM sig, SCM proc)
  132. {
  133.   long s = STk_integer_value(sig);
  134.  
  135.   if (s == LONG_MIN || s < 0 || s >= MAX_SIGNAL)
  136.     STk_err("add-signal-handler!: bad signal number", sig);
  137.  
  138.   if (STk_procedurep(proc) == Ntruth) 
  139.     STk_err("add-signal-handler!: bad procedure", proc);
  140.  
  141.   return signals[s] = (BOOLEANP(signals[s]) ? LIST1(proc) : Cons(proc,signals[s]));
  142. }
  143.  
  144. PRIMITIVE STk_get_signal_handlers(SCM sig)
  145. {
  146.   if (sig == UNBOUND) {                /* Return all handlers */
  147.     SCM z;
  148.   
  149.     z = STk_makevect(MAX_SIGNAL, NULL);
  150.     memcpy(VECT(z), signals, MAX_SIGNAL * sizeof(SCM));
  151.     return z; 
  152.   }
  153.   else {                    /* Return handlers of sig only */
  154.     long s = STk_integer_value(sig);
  155.  
  156.     if (s == LONG_MIN || s < 0 || s >= MAX_SIGNAL)
  157.       STk_err("get-signal-handlers: bad signal number", sig);
  158.     return signals[s];
  159.   }
  160. }
  161.  
  162. void STk_mark_signal_table(void)
  163. {
  164.   int i;
  165.  
  166.   for (i = 0; i < MAX_SIGNAL; i++) 
  167.     STk_gc_mark(signals[i]);
  168. }
  169.  
  170. void STk_init_signal(void)
  171. {
  172.   int i;
  173.  
  174.   for (i = 0; i < MAX_SIGNAL; i++) {
  175.     signals[i] = (
  176. #ifdef SIGSTP
  177.       (i==SIGTSTP) || /* ^Z is reset to default to allow program supension */
  178. #endif
  179. #ifdef SIGABRT
  180.       (i== SIGABRT) || /* Really abort when receiving  ABORT (loops otherwise)*/
  181. #endif
  182. #ifdef SIGQUIT
  183.       (i == SIGQUIT) || /* ditto for QUIT */
  184. #endif
  185.       0) ? Ntruth : NIL;
  186.     /* Treat specially SIGINT (^C) */
  187.     signals[SIGINT] = NIL;
  188. #ifdef  HAVE_SIGACTION
  189.     {
  190.       /* Use the secure Posix.1 way */
  191.       struct sigaction sigact;
  192.       
  193.       sigemptyset(&(sigact.sa_mask));
  194.       sigact.sa_handler = NULLP(signals[i])? STk_handle_signal : SIG_DFL;
  195.       sigact.sa_flags   = SA_FLAGS;
  196.       sigaction(i, &sigact, NULL);
  197.     }
  198. #else
  199.     signal(i, STk_handle_signal);
  200. #endif
  201.   }
  202.  
  203.   /* 
  204.    * POSIX.1 signals 
  205.    */
  206. #ifdef SIGABRT
  207.   VCELL(Intern("SIGABRT")) = STk_makeinteger(SIGABRT);
  208. #endif
  209. #ifdef SIGALRM
  210.   VCELL(Intern("SIGALRM")) = STk_makeinteger(SIGALRM);
  211. #endif
  212. #ifdef SIGFPE
  213.   VCELL(Intern("SIGFPE")) = STk_makeinteger(SIGFPE);
  214. #endif
  215. #ifdef SIGHUP
  216.   VCELL(Intern("SIGHUP")) = STk_makeinteger(SIGHUP);
  217. #endif
  218. #ifdef SIGILL
  219.   VCELL(Intern("SIGILL")) = STk_makeinteger(SIGILL);
  220. #endif
  221. #ifdef SIGINT
  222.   VCELL(Intern("SIGINT")) = STk_makeinteger(SIGINT);
  223. #endif
  224. #ifdef SIGKILL
  225.   VCELL(Intern("SIGKILL")) = STk_makeinteger(SIGKILL);
  226. #endif
  227. #ifdef SIGPIPE
  228.   VCELL(Intern("SIGPIPE")) = STk_makeinteger(SIGPIPE);
  229. #endif
  230. #ifdef SIGQUIT
  231.   VCELL(Intern("SIGQUIT")) = STk_makeinteger(SIGQUIT);
  232. #endif
  233. #ifdef SIGSEGV
  234.   VCELL(Intern("SIGSEGV")) = STk_makeinteger(SIGSEGV);
  235. #endif
  236. #ifdef SIGTERM
  237.   VCELL(Intern("SIGTERM")) = STk_makeinteger(SIGTERM);
  238. #endif
  239. #ifdef SIGUSR1
  240.   VCELL(Intern("SIGUSR1")) = STk_makeinteger(SIGUSR1);
  241. #endif
  242. #ifdef SIGUSR2
  243.   VCELL(Intern("SIGUSR2")) = STk_makeinteger(SIGUSR2);
  244. #endif
  245.  
  246.   /* 
  247.    * Following signals exist only on system which support Job Control 
  248.    */
  249. #ifdef SIGCHLD
  250.   VCELL(Intern("SIGCHLD")) = STk_makeinteger(SIGCHLD);
  251. #endif
  252. #ifdef SIGCONT
  253.   VCELL(Intern("SIGCONT")) = STk_makeinteger(SIGCONT);
  254. #endif
  255. #ifdef SIGSTOP
  256.   VCELL(Intern("SIGSTOP")) = STk_makeinteger(SIGSTOP);
  257. #endif
  258. #ifdef SIGTSTP
  259.   VCELL(Intern("SIGTSTP")) = STk_makeinteger(SIGTSTP);
  260. #endif
  261. #ifdef SIGTTIN
  262.   VCELL(Intern("SIGTTIN")) = STk_makeinteger(SIGTTIN);
  263. #endif
  264. #ifdef SIGTTOU
  265.   VCELL(Intern("SIGTTOU")) = STk_makeinteger(SIGTTOU);
  266. #endif
  267.  
  268.   /*
  269.    * Non POSIX signals stolen on Suns and Linux
  270.    */
  271.  
  272. #ifdef SIGTRAP
  273.   VCELL(Intern("SIGTRAP")) = STk_makeinteger(SIGTRAP);
  274. #endif
  275. #ifdef SIGIOT
  276.   VCELL(Intern("SIGIOT")) = STk_makeinteger(SIGIOT);
  277. #endif
  278. #ifdef SIGEMT
  279.   VCELL(Intern("SIGEMT")) = STk_makeinteger(SIGEMT);
  280. #endif
  281. #ifdef SIGBUS
  282.   VCELL(Intern("SIGBUS")) = STk_makeinteger(SIGBUS);
  283. #endif
  284. #ifdef SIGSYS
  285.   VCELL(Intern("SIGSYS")) = STk_makeinteger(SIGSYS);
  286. #endif
  287. #ifdef SIGURG
  288.   VCELL(Intern("SIGURG")) = STk_makeinteger(SIGURG);
  289. #endif
  290. #ifdef SIGCLD
  291.   VCELL(Intern("SIGCLD")) = STk_makeinteger(SIGCLD);
  292. #endif
  293. #ifdef SIGIO
  294.   VCELL(Intern("SIGIO")) = STk_makeinteger(SIGIO);
  295. #endif
  296. #ifdef SIGPOLL
  297.   VCELL(Intern("SIGPOLL")) = STk_makeinteger(SIGPOLL);
  298. #endif
  299. #ifdef SIGXCPU
  300.   VCELL(Intern("SIGXCPU")) = STk_makeinteger(SIGXCPU);
  301. #endif
  302. #ifdef SIGXFSZ
  303.   VCELL(Intern("SIGXFSZ")) = STk_makeinteger(SIGXFSZ);
  304. #endif
  305. #ifdef SIGVTALRM
  306.   VCELL(Intern("SIGVTALRM")) = STk_makeinteger(SIGVTALRM);
  307. #endif
  308. #ifdef SIGPROF
  309.   VCELL(Intern("SIGPROF")) = STk_makeinteger(SIGPROF);
  310. #endif
  311. #ifdef SIGWINCH
  312.   VCELL(Intern("SIGWINCH")) = STk_makeinteger(SIGWINCH);
  313. #endif
  314. #ifdef SIGLOST
  315.   VCELL(Intern("SIGLOST")) = STk_makeinteger(SIGLOST);
  316. #endif
  317.  
  318.   /* Add GC signal */
  319.   VCELL(Intern("SIGHADGC")) = STk_makeinteger(SIGHADGC);
  320. }
  321.  
  322.